/**
 *  Copyright (C) 2014 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

function moxingid(part){
	$("#inptchange").val(part);
    $("#inptchange").trigger("input");
}

(function () {
	"use strict";

	angular.module("3drepo")
		.directive("tree", tree);

	function tree() {
		return {
			restrict: "EA",
			templateUrl: "tree.html",
			scope: {
				account:  "=",
				project:  "=",
				branch:   "=",
				revision: "=",
				filterText: "=",
				onContentHeightRequest: "&"
			},
			controller: TreeCtrl,
			controllerAs: "vm",
			bindToController: true
		};
	}

	TreeCtrl.$inject = ["$scope", "$timeout", "TreeService", "EventService"];

	/**
	 *
	 * @param $scope
	 * @param $timeout
	 * @param TreeService
	 * @param EventService
	 * @constructor
	 */
	function TreeCtrl($scope, $timeout, TreeService, EventService) {
		var vm = this,
			promise = null,
			i = 0,
			length = 0,
			currentSelectedNode = null,
			currentScrolledToNode = null,
			highlightSelectedViewerObject = true,
			clickedHidden = {}, // Nodes that have actually been clicked to hide
			clickedShown = {}, // Nodes that have actually been clicked to show
			multiSelectMode = false;

		/*
		 * Init
		 */
		var idbox;
		var allidsbox;
		
		vm.nodes = [];
		vm.showNodes = true;
		vm.showTree = true;
		vm.showFilterList = false;
		vm.currentFilterItemSelected = null;
		vm.viewerSelectedObject = null;
		vm.showProgress = true;
		vm.progressInfo = "Loading full tree structure";
		vm.onContentHeightRequest({height: 70}); // To show the loading progress
		vm.visible   = {};
		vm.invisible = {};

		/**
		 * Set the content height.
		 * The height of a node is dependent on its name length and its level.
		 *
		 * @param {Array} nodesToShow
		 */
		function setContentHeight (nodesToShow) {
			var i, length,
				height = 0,
				nodeMinHeight = 42,
				maxStringLength = 35, maxStringLengthForLevel = 0,
				lineHeight = 18, levelOffset = 2;

			for (i = 0, length = nodesToShow.length; i < length ; i += 1) {
				maxStringLengthForLevel = maxStringLength - (nodesToShow[i].level * levelOffset);
				if (nodesToShow[i].hasOwnProperty("name")) {
					height += nodeMinHeight + (lineHeight * Math.floor(nodesToShow[i].name.length / maxStringLengthForLevel));
				}
				else {
					height += nodeMinHeight + lineHeight;
				}
			}
			vm.onContentHeightRequest({height: height});
		}

		/**
		 * Initialise the tree nodes to show to the first node
		 */
		function initNodesToShow () {
			vm.nodesToShow = [vm.allNodes[0]];
			vm.nodesToShow[0].level = 0;
			vm.nodesToShow[0].expanded = false;
			vm.nodesToShow[0].selected = false;
			vm.nodesToShow[0].hasChildren = vm.nodesToShow[0].children;

			// Only make the top node visible if it does not have a toggleState
			if (!vm.nodesToShow[0].hasOwnProperty("toggleState")) {
				vm.nodesToShow[0].toggleState = "visible";
			}
		}

		/**
		 * Show the first set of children using the expand function but deselect the child used for this
		 */
		function expandFirstNode () {
			expandToSelection(vm.nodesToShow[0].children[0].path.split("__"), 0, true);
			vm.nodesToShow[0].children[0].selected = false;
		}

		/**
		 * traverse children of a node recursively
		 * @param {Object} node
		 * @param {Function} callback
		 */
		function traverseNode(node, callback){
			callback(node);
			node.children && node.children.forEach(function(child){
				traverseNode(child, callback);
			});
		}

		function getAccountProjectKey(account, project)
		{
			return account + "@" + project;
		}

		/**
		 * Add all child id of a node recursively, the parent node's id will also be added.
		 * @param {Object} node
		 * @param {Array} nodes Array to push the nodes to
		 */
		function traverseNodeAndPushId(node, nodes){
			traverseNode(node, function(node){
				if (!node.children && ((node.type || "mesh") === "mesh"))
				{
					var key = getAccountProjectKey(node.account, node.project);
					if(!nodes[key]){
						nodes[key] = [];
					}

					nodes[key].push(node._id);
				}
			});
		}

		function getVisibleArray(account, project){
			var key = getAccountProjectKey(account, project);
			if(!vm.visible[key]){
				vm.visible[key] = new Set();
			}

			return vm.visible[key];
		}

		function getInvisibleArray(account, project){
			var key = getAccountProjectKey(account, project);
			if(!vm.invisible[key]){
				vm.invisible[key] = new Set();
			}

			return vm.invisible[key];
		}

		/**
		 * Set the toggle state of a node
		 * @param {Object} node Node to change the visibility for
		 * @param {String} visibility Visibility to change to
		 */
		vm.setToggleState = function(node, visibility)
		{
			var visible = getVisibleArray(node.account, node.project);
			var invisible = getInvisibleArray(node.account, node.project);

			if (!node.children && ((node.type || "mesh") === "mesh"))
			{
				if (visibility === "invisible")
				{
					if (invisible.has(node._id))
					{
						invisible.delete(node._id);
					} else {
						invisible.add(node._id);
					}

					visible.delete(node._id);
				} else {
					if (visible.has(node._id))
					{
						visible.delete(node._id);
					} else {
						visible.add(node._id);
					}

					invisible.delete(node._id);
				}
			}

			node.toggleState = visibility;
		};

		/*
		* See if id in each ids is a sub string of path
		*/
		function matchPath(ids, path){

			for(var i=0; i<ids.length; i++){
				if(path.indexOf(ids[i]) !== -1){
					return true;
				}
			}

			return false;
		}

		/**
		 * Expand a node to show its children.
		 * @param event
		 * @param _id
		 */
		vm.expand = function (event, _id) {
			var i, length,
				j, jLength,
				numChildren = 0,
				index = -1,
				endOfSplice = false,
				numChildrenToForceRedraw = 3;

			event.stopPropagation();

			// Find node index
			for (i = 0, length = vm.nodesToShow.length; i < length; i += 1) {
				if (vm.nodesToShow[i]._id === _id) {
					index = i;
					break;
				}
			}

			var _ids = [_id];
			// Found
			if (index !== -1) {
				if (vm.nodesToShow[index].hasChildren) {
					if (vm.nodesToShow[index].expanded) {
						// Collapse

						//if the target itself contains subProjectTree
						if(vm.nodesToShow[index].hasSubProjTree){
							//node containing sub project tree must have only one child
							var subProjectNode = vm.subTreesById[vm.nodesToShow[index].children[0]._id];
							_ids.push(subProjectNode._id);
						}

						while (!endOfSplice) {

							if (angular.isDefined(vm.nodesToShow[index + 1]) && matchPath(_ids, vm.nodesToShow[index + 1].path)) {

								if(vm.nodesToShow[index + 1].hasSubProjTree){
									var subProjectNode = vm.subTreesById[vm.nodesToShow[index + 1].children[0]._id];
									_ids.push(subProjectNode._id);
								}

								vm.nodesToShow.splice(index + 1, 1);

							} else {
								endOfSplice = true;
							}
						}
					} else {
						// Expand
						numChildren = vm.nodesToShow[index].children.length;

						// If the node has a large number of children then force a redraw of the tree to get round the display problem
						if (numChildren >= numChildrenToForceRedraw) {
							vm.showNodes = false;
						}

						for (i = 0; i < numChildren; i += 1) {
							// For federation - handle node of project that cannot be viewed or has been deleted
							// That node will be below level 0 only
							if ((vm.nodesToShow[index].level === 0) &&
								vm.nodesToShow[index].children[i].hasOwnProperty("children") &&
								vm.nodesToShow[index].children[i].children[0].hasOwnProperty("status")) {

								vm.nodesToShow[index].children[i].status = vm.nodesToShow[index].children[i].children[0].status;

							}
							else {
								// Normal tree node
								vm.nodesToShow[index].children[i].expanded = false;

								// If the child node does not have a toggleState set it to visible
								if (!vm.nodesToShow[index].children[i].hasOwnProperty("toggleState")) {
									vm.setToggleState(vm.nodesToShow[index].children[i], "visible");
								}

							}

							// A child node only "hasChildren", i.e. expandable, if any of it's children have a name
							vm.nodesToShow[index].children[i].level = vm.nodesToShow[index].level + 1;
							vm.nodesToShow[index].children[i].hasChildren = false;
							if (("children" in vm.nodesToShow[index].children[i]) && (vm.nodesToShow[index].children[i].children.length > 0)) {
								for (j = 0, jLength = vm.nodesToShow[index].children[i].children.length; j < jLength; j++) {
									if (vm.nodesToShow[index].children[i].children[j].hasOwnProperty("name")) {
										vm.nodesToShow[index].children[i].hasChildren = true;
										break;
									}
								}
							}

							if(vm.nodesToShow[index].children[i].hasOwnProperty("name")){
								vm.nodesToShow.splice(index + i + 1, 0, vm.nodesToShow[index].children[i]);
							}
							
						}

						// Redraw the tree if needed
						if (!vm.showNodes) {
							$timeout(function () {
								vm.showNodes = true;
								// Resize virtual repeater
								// Taken from kseamon's comment - https://github.com/angular/material/issues/4314
								$scope.$broadcast('$md-resize');
							});
						}
					}
					vm.nodesToShow[index].expanded = !vm.nodesToShow[index].expanded;
				}
			}

			setContentHeight(vm.nodesToShow);
		};

		/**
		 * Expand the tree and highlight the node corresponding to the object selected in the viewer.
		 * @param path
		 * @param level
		 */

		var lastParentWithName = null;

		var cnoesid=[];
        var boif=null;
		function expandToSelection(path, level, noHighlight) {
			var hcsi=[];
		    console.log(path);
		    console.log(level);

            var idpar,
				 idch,
			     leftid,
				 leftcid;
				 

			var i, j, length, childrenLength, selectedId = path[path.length - 1], selectedIndex = 0, selectionFound = false;

			// Force a redraw of the tree to get round the display problem
			vm.showNodes = false;
			var condLoop = true;
			for (i = 0, length = vm.nodesToShow.length; i < length && condLoop; i += 1) {
				if (vm.nodesToShow[i]._id === path[level]) {

					//console.log('name', vm.nodesToShow[i].name);
					//console.log('selectedId', selectedId);
					//console.log('length', vm.nodesToShow.length)
					
					lastParentWithName = vm.nodesToShow[i];

					vm.nodesToShow[i].expanded = true;
					vm.nodesToShow[i].selected = false;
					childrenLength = vm.nodesToShow[i].children.length;

					if (level === (path.length - 2)) {
						selectedIndex = i;
					}

					var childWithNameCount = 0;

					for (j = 0; j < childrenLength; j += 1) {
						// Set child to not expanded
						vm.nodesToShow[i].children[j].expanded = false;

						if (vm.nodesToShow[i].children[j]._id === selectedId) {

							if (vm.nodesToShow[i].children[j].hasOwnProperty("name")) {
								//console.log('selected', vm.nodesToShow[i].children[j].name);
								vm.nodesToShow[i].children[j].selected = true;
								lastParentWithName = null;
								selectedIndex = i + j + 1;

							}
							else if(!noHighlight){
								// If the selected mesh doesn't have a name highlight the parent in the tree
								// highlight the parent in the viewer

								vm.selectNode(vm.nodesToShow[i]);
								selectedId = vm.nodesToShow[i]._id;
								selectedIndex = i;
								//console.log('selectedIndex', selectedIndex);
								//console.log(vm.nodesToShow[i]);
								lastParentWithName = null;
								//console.log('vm.nodesToShow[i]', vm.nodesToShow[i]);
								selectedId = vm.nodesToShow[i]._id;
							}

							condLoop = false;
						}
						else {
							// This will clear any previously selected node
							vm.nodesToShow[i].children[j].selected = false;

							if(urlname=="plan"||urlname=="real"||urlname=="report"||urlname=="construct"||urlname=="check"||urlname=="patrol"||urlname=="build"||urlname=="division"||urlname=="branch"||urlname=="item"){
								for(var qp=0;qp<leftextid.length;qp++){
									if(vm.nodesToShow[i].children[j]._id==leftextid[qp]){
										hcsi.push({"par": i, "chil":j});
									}
								}
							} else {
								$(".ng-binding").removeClass("viewerSelected");
							}
						}

						// Only set the toggle state once when the node is listed
						if (!vm.nodesToShow[i].children[j].hasOwnProperty("toggleState")) {
							vm.setToggleState(vm.nodesToShow[i].children[j], "visible");
						}

						// Determine if child node has childern
						vm.nodesToShow[i].children[j].hasChildren = false;
						if (("children" in vm.nodesToShow[i].children[j]) && (vm.nodesToShow[i].children[j].children.length > 0)) {
							for (var k = 0, jLength = vm.nodesToShow[i].children[j].children.length; k < jLength; k++) {
								if (vm.nodesToShow[i].children[j].children[k].hasOwnProperty("name")) {
									vm.nodesToShow[i].children[j].hasChildren = true;
									break;
								}
							}
						}

						// Set current selected node
						if (vm.nodesToShow[i].children[j].selected) {
							selectionFound = true;
							currentSelectedNode = vm.nodesToShow[i].children[j];

							if(urlname=="plan"||urlname=="real"||urlname=="report"||urlname=="construct"||urlname=="check"||urlname=="patrol"||urlname=="build"||urlname=="division"||urlname=="branch"||urlname=="item"){
								idpar=i;
								idch=j;
								for(var qpz=0;qpz<leftextid.length;qpz++){
									if(vm.nodesToShow[i].children[j]._id==leftextid[qpz]){
	
										console.log(i+"--"+j);
										leftextid.splice(qpz,1);
										console.log(leftextid);
	
										leftid=i;
										leftcid=j;
									}
								}
							}
						}


						vm.nodesToShow[i].children[j].level = level + 1;

						if(vm.nodesToShow[i].hasChildren && vm.nodesToShow[i].children[j].hasOwnProperty('name')){

							vm.nodesToShow.splice(i + childWithNameCount + 1, 0, vm.nodesToShow[i].children[j]);
							childWithNameCount++;
						}
						
					}
				}
			}

			console.log(hcsi);
            if(urlname=="plan"||urlname=="real"||urlname=="report"||urlname=="construct"||urlname=="check"||urlname=="patrol"||urlname=="build"||urlname=="division"||urlname=="branch"||urlname=="item"){

            $.each(hcsi,function (ns,ls) {
                vm.nodesToShow[ls.par].children[ls.chil].selected =true;
            });
            if(leftid!=undefined){
                vm.nodesToShow[leftid].children[leftcid].selected =false;
			}
                if(cnoesid.length>0){

                    if(idpar!=undefined&&idch!=undefined){

                        for(var m=0;m<cnoesid.length;m++){
                            if(idpar==cnoesid[m].par&&idch==cnoesid[m].chil){
                                vm.nodesToShow[idpar].children[idch].selected=false;
                                cnoesid.splice(m,1);
                                console.log(cnoesid);
                                for(var yy=0;yy<leftextid.length;yy++){
                                    if(vm.nodesToShow[idpar].children[idch]._id==leftextid[yy]){
                                        leftextid.splice(yy,1);
                                        console.log(leftextid);
                                    }
                                }
                            }else {
                                if(m==cnoesid.length-1){
                                    if(leftid==undefined){

                                        cnoesid.push({"par": idpar, "chil": idch});
                                        leftextid.push(vm.nodesToShow[idpar].children[idch]._id);
                                    }
                                    console.log(leftextid);
                                    break;
                                }
                            }
                        }

                        console.log(cnoesid);
                        console.log(leftextid);
                        $.each(cnoesid,function (ns,ls) {
                            vm.nodesToShow[ls.par].children[ls.chil].selected =true;
                        });
                    }

                }else{
                    if(idpar!=undefined&&idch!=undefined) {

                        if(leftid==undefined){

                            cnoesid.push({"par": idpar, "chil": idch});
                            leftextid.push(vm.nodesToShow[idpar].children[idch]._id);
                        }
                    }
                }
			}
			
			if (level < (path.length - 2)) {
				expandToSelection(path, (level + 1));
			} else if (level === (path.length - 2)) {
				setContentHeight(vm.nodesToShow);
				vm.showNodes = true;
				$timeout(function() {
					// Redraw the tree

					// Resize virtual repeater

					// Taken from kseamon's comment - https://github.com/angular/material/issues/4314
					$scope.$broadcast('$md-resize');
					//console.log('this selectedIndex', selectedIndex);
					vm.topIndex = selectedIndex;
				});

				$timeout(function(){
					var el = document.getElementById(selectedId);
					if(!el){
						//console.log('el not found')
					}
					el && el.scrollIntoView();
				});

			}
		}

		$scope.$watch(EventService.currentEvent, function(event) {
			if (event.type === EventService.EVENT.VIEWER.OBJECT_SELECTED) {
				if ((event.value.source !== "tree") && highlightSelectedViewerObject)
				{
					var objectID = event.value.id;

					if (objectID)
					{
						var path;
						if(vm.idToPath[objectID]){
							path = vm.idToPath[objectID].split("__");
						} else {
							path = vm.subProjIdToPath[objectID].split("__");
							var parentPath = vm.subTreesById[path[0]].parent.path.split("__");
							path = parentPath.concat(path);
						}

						initNodesToShow();
						//console.log('path', path);
						lastParentWithName = null;
						expandToSelection(path, 0);
						//console.log('lastParentWithName', lastParentWithName);
						lastParentWithName && vm.selectNode(lastParentWithName);
					}
				}
			}
			else if (event.type === EventService.EVENT.VIEWER.BACKGROUND_SELECTED) {
				// Remove highlight from any selected node in the tree
				if (currentSelectedNode !== null) {
					currentSelectedNode.selected = false;
					currentSelectedNode = null;
					if (vm.currentFilterItemSelected !== null) {
						vm.currentFilterItemSelected.class = "";
						vm.currentFilterItemSelected = null;
					}
				}
			}
			else if ((event.type === EventService.EVENT.PANEL_CARD_ADD_MODE) ||
					 (event.type === EventService.EVENT.PANEL_CARD_EDIT_MODE)) {
				// If another card is in modify mode don't show a node if an object is clicked in the viewer
				highlightSelectedViewerObject = !event.value.on;
			}
			else if (event.type === EventService.EVENT.MULTI_SELECT_MODE) {
				multiSelectMode = event.value;
			}
			else if (event.type === EventService.EVENT.TREE_READY){
				/*
				 * Get all the tree nodes
				 */

				vm.allNodes = [];
				vm.allNodes.push(event.value.nodes);
				vm.nodes = vm.allNodes;
				vm.showTree = true;
				vm.showProgress = false;
				vm.subTreesById = event.value.subTreesById;
				vm.idToPath = event.value.idToPath;
				vm.subProjIdToPath = event.value.subProjIdToPath;

				initNodesToShow();
				expandFirstNode();
				setupInfiniteScroll();
				setContentHeight(vm.nodesToShow);

	            //所有节点
				idbox=vm.nodes;
				allidsbox=vm.nodes;
				console.log(idbox);
				var allisshux=JSON.stringify(vm.nodes);
				sessionStorage.setItem("allisshux",allisshux);
			}
		});

		var tempData = [];
		function eachChildren(data, reset = 1){
			if (reset){
                tempData = [];
			}
			var re = re;
            tempData.push(data._id);
			if(data.children.length){
                $.each(data.children, function(index, el){
                    eachChildren(el, 0);
                })
			}

			return tempData;
		}



        var allids= null;
		//点击构件勾选，选中与未选中操作建立链接发送到后台
		vm.toggleTreeNode = function (node) {
			//当前选中所有_id
			var dataz = eachChildren(node);
			if (allids === null){
				//整个树形_id
				allids = eachChildren(idbox[0]);
			}

			var i, j,
				nodesLength,
				path,
				hasParent,
				lastParent = node,
				nodeToggleState = "visible",
				numInvisible = 0,
				numParentInvisible = 0;

			vm.toggledNode = node;

			//toggle yourself
			vm.setToggleState(node, (node.toggleState === "visible") ? "invisible" : "visible");
			nodeToggleState = node.toggleState;
			updateClickedHidden(node);
			updateClickedShown(node);

			
					//建立长链接发送数据到后台
					var diase=vm.nodesToShow[i].toggleState === "visible";
					//如果是选中则合并两个数组_id
                    console.log(allids);
                    if (diase==true){
                    	console.log("true");
                        allids = allids.concat(dataz);
					}else {
                        console.log("false");
                    	//未选中从全部_id中删除当前操作的_id
                    	for(var k in dataz){
							// var temp = allids.indexOf(data[i]);

							allids.splice(allids.indexOf(dataz[k]), 1);
						}
					}
                    console.log(allids);
                    var data = {
                        _ids:allids,
                        type:diase
                    };

                    // sendSocket('showOrHide_component', data);通过树形菜单勾选，得到id新建

			var stack = [node];
			var head = null;

			while (stack.length > 0)
			{
				var head = stack.pop();

				if (node !== head) {
					vm.setToggleState(head, nodeToggleState);
				}

				if (head.children)
				{
					for(var i = 0; i < head.children.length; i++)
					{
						stack.push(head.children[i]);
					}
				}
			}

			//a__b .. c__d
			//toggle parent
			path = node.path.split("__");
			path.splice(path.length - 1, 1);

			for (i = 0, nodesLength = vm.nodesToShow.length; i < nodesLength; i += 1) {
			// 	// Get node parent
				if (vm.nodesToShow[i]._id === path[path.length - 1]) {

					lastParent = vm.nodesToShow[i];
					hasParent = true;

				} else if(lastParent.parent){

					//Get node parent and reconstruct the path in case it is a fed project
					lastParent = lastParent.parent;
					path = lastParent.path.split("__").concat(path);
					hasParent = true;
				}
			}

			// Set the toggle state of the nodes above
			if (hasParent) {
				for (i = (path.length - 1); i >= 0; i -= 1) {
					for (j = 0, nodesLength = vm.nodesToShow.length; j < nodesLength; j += 1) {
						if (vm.nodesToShow[j]._id === path[i]) {
							numInvisible = vm.nodesToShow[j].children.reduce(
								function (total, child) {
									return child.toggleState === "invisible" ? total + 1 : total;
								},
								0);
							numParentInvisible = vm.nodesToShow[j].children.reduce(
								function (total, child) {
									return child.toggleState === "parentOfInvisible" ? total + 1 : total;
								},
								0);

							if (numInvisible === vm.nodesToShow[j].children.length) {
								vm.nodesToShow[j].toggleState = 'invisible';
							} else if ((numParentInvisible + numInvisible) > 0) {
								vm.nodesToShow[j].toggleState = 'parentOfInvisible';
							} else {
								vm.setToggleState(vm.nodesToShow[j], "visible");
							}
						}
					}
				}
			}

			toggleNode(node);
		};

		var toggleNode = function (node) {
			var childNodes = {};
			var pathArr = [];
			var idx = 0, i = 0;

			traverseNodeAndPushId(node, childNodes);

			if (node.toggleState === "invisible")
			{
				for(var key in childNodes)
				{
					for(var i = 0; i < childNodes[key].length; i++)
					{
						vm.invisible[key].add(childNodes[key][i]);
						vm.visible[key].delete(childNodes[key][i]);
					}
				}
			} else {
				for(var key in childNodes)
				{
					for(var i = 0; i < childNodes[key].length; i++)
					{
						vm.visible[key].add(childNodes[key][i]);
						vm.invisible[key].delete(childNodes[key][i]);
					}
				}
			}

			for (var key in vm.visible){

				var vals = key.split('@');
				var account = vals[0];
				var project = vals[1];

				EventService.send(EventService.EVENT.VIEWER.SWITCH_OBJECT_VISIBILITY, {
					source: "tree",
					account: account,
					project: project,
					name: node.name,
					visible_ids: getVisibleArray(account, project),
					invisible_ids: getInvisibleArray(account, project)
				});
			}

		};

		
        //选中文字控件改变颜色
        var urlname=getUrlParam("action");
        if(urlname=="plan"||urlname=="real"||urlname=="report"||urlname=="construct"||urlname=="check"||urlname=="patrol"||urlname=="build"||urlname=="division"||urlname=="branch"||urlname=="item"){

		}else{
            $("body").on("click",".ng-binding",function () {
                $(".ng-binding").removeClass("viewerSelected");
                $(this).addClass("viewerSelected");

            });
		}


        //根据链接地址截取sn参数
        function getUrlParam(name){
            var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
            var r = window.location.search.substr(1).match(reg);
            if (r!=null) return unescape(r[2]); return null;
        }
        var names=getUrlParam('sn');
        if(names!=null){
           $("#leftButtons,#rightButtons,#rightPanel").css("display","none");
           $("#showButtonIcon").parent("button").css("display","none");
        }

        //关闭模型菜单
        if(getUrlParam('action')=="analysis"){
        	$("#leftPanel").hide();
        }

        //模型管理显示隐藏菜单
        if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
            if(getUrlParam('action')=="index"){
                $("#leftPanel").css("margin-top","-1400px");
                $("#showButtonIcon").parent("button").css("display","block");
                $("#showButtonIcon").parent("button").css("margin-left","222px");

            }

        } else {
            if(getUrlParam('action')=="index"){
                $("#leftButtons,#rightButtons,#rightPanel").css("display","block");
                $("#showButtonIcon").parent("button").css("display","block");
                $("#showButtonIcon").parent("button").css("margin-left","222px");
            }
        }

        $("#showButtonIcon").click(function (){
            if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
                if(getUrlParam('action')=="index"){
                    $("#leftButtons,#rightButtons,#rightPanel").css("display","block");
                    $("#showButtonIcon").parent("button").css("display","block");


                    $("#showButtonIcon").parent("button").css("margin-left","222px");
                    // $("#leftPanel").css("margin-top","0");
				}
            }

		})

		
		$("body").on("click","#rightPanel #buttons .panelButtonGroup ",function () {
            $("#rightPanel #items").css("opacity","1");

             sendSocket('closeInfo_component', {});
        })
        // window.parent.document.getElementsByClassName(".addgoujian").hide();;

        var inputchange='<input id="inptchange" type="hidden">';
        $("body").before(inputchange);
        $("#inptchange").bind("input propertychange",function () {


            var nnbox=$("#inptchange").val();




				var data = {
					_id:nnbox
				};
				console.log(data);
				sendSocket('click_component', data);
				if(getUrlParam("action")=="Safety_index"){
					setTimeout(function(){
						var data = {
							_id:nnbox,
							account:sessionStorage.getItem("account"),
							norm:sessionStorage.getItem("norm"),
							position:sessionStorage.getItem("position"),
							project:sessionStorage.getItem("project")
						};
						console.log(data);

						sendSocket('click_component', data);
					},500);
				}



            //点击安全点
            sendSocket('click_safetyPoint', data);
           $("#rightPanel #items").css("opacity","0");

               setTimeout(function () {
                   var idspar=sessionStorage.getItem("idspart");

                   var parids=[];
                   parids=idspar.split(",");
                   console.log(parids);
                   var data = {
                       _ids:parids,
                       type:true
                   };

                   sendSocket('showOrHide_component', data);
               },1000)



            // $("#rightPanel #buttons .panelButtonGroup").click();

        });
        var animation;
        //webstork长链接
        var snbox =getUrlParam('sn');
        if(snbox){
            snbox=snbox.replace(/\s+/g,"+");
        }else{
            console.log("模型");

        }
        var rgbjih=null;
        var rgbwjh=null;
        var rgb02,rgb03,rgb04,rgb05;
        var server =server_config.bdiphost + '/engine/' + snbox; // websocket服务器
        var ws = new WebSocket("ws://"+server);
        ws.onopen = function(){
            // 当连接成功时，会执行此处的代码
            // 发送消息到服务器
            // sendSocket('engineConnect', {});
        }
        var web_fd = '';
        ws.onmessage = function(response){
            // 此处执行收到消息后的业务逻辑
            var result = JSON.parse(response.data);
            var data = result.data;
            switch(result.type){
                case '':
                    // 记录WEB端fd连接标识
                    web_fd = data.web_fd;
                    break;
            }

            if(rgbjih===null){

                rgbjih=data.rgb[1];
                rgbwjh=data.rgb[0];
                rgb02=data.rgb[2];
                rgb03=data.rgb[3];
                rgb04=data.rgb[4];
                rgb05=data.rgb[5];

			}

            if(result.type=="create_projectTask"||result.type=="update_projectTask"){
                if(data.code==200){
                    tempData = [];
                    sessionStorage.setItem("addeditcolor",true);
                    //树形菜单勾选新建任务和编辑成功后，全部勾选
                    // $(".md-virtual-repeat-offsetter .repeated-item").eq(0).children(".layout-row").children(".treeButton").eq(1).click();

                }
			}
			if(result.type=="relationModel_constructionDaily"||result.type=="relationModel_constructionProgress"){
                sessionStorage.setItem("addeditcolor",true);
			}
            if(result.type=="inputReal_component"){
            	//实际进度录入成功后，勾选全部树形菜单
                sessionStorage.setItem("addeditcolor",true);
                // $(".md-virtual-repeat-offsetter .repeated-item").eq(0).children(".layout-row").children(".treeButton").eq(1).click();
            }

            //模型动画
			if(result.type=="plannedTask_projectTask"){
                animation=result.data;

			}
			if(result.type=="drag_projectTask"){
				console.log(data.date);
                var timestamp = Date.parse(new Date(data.date));
                timestamp = timestamp / 1000;

				var anmation=[];
				$.each(animation.components,function (t,ls) {
                   //console.log(new Date(ls.taskdata.plan_begin_time*1000).toLocaleDateString());
                   if(ls.taskdata.plan_begin_time<=timestamp){
                       anmation.push(ls._id);
				   }

                })

                ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                ViewerService.defaultViewer.setVisibilityByID(anmation,true);
			}

            if(result.type=="create_planNode"){
            	//节点创建成功，对未计划和计划的构件颜色进行改变0
				//全部id变成灰色
                if(data.code==200){

                    //alert(result.data.progress)chodikkkkdfoijf666;

                    yanse();
                    $(".md-virtual-repeat-offsetter .repeated-item").eq(0).children(".layout-row").children(".treeButton").eq(1).click();

				}else{
				}
			}
			if(result.type=="click_projectNode"){
                sessionStorage.setItem("datouzheng","true");
                yanse();
			}
			//编辑计划进度
            if(result.type=="update_planNode"||result.type=="update_planGradation"){
                if(data.code==200){

                    yanse();
                }else{
				}
            }

            if(result.type=="searchPlanByTime_component"){
                if(data.code==200){

                    yanse();
                }else{
                	alert(data.msg);
                }
			}
			if(result.type=="index_safetyPoint"){
            	console.log(data);
            	var ndx=JSON.stringify(data.info);
                sessionStorage.setItem("anqundiansz",ndx);

			}

            if(result.type=="component_danger"){
                console.log(data);
                var wxd=JSON.stringify(data.safetyPoint);
                sessionStorage.setItem("weixiandian",wxd);
                sendSocket('closeInfo_component', {});

            }

			//日报管理管理模型
			if(result.type=="showRelation_constructionDaily"){
                if(data.code==200){

                    yanse();
                }else{
                    alert(data.msg);
                }
			}

			//施工进度
			if(result.type=="showRelation_constructionProgress"){
                if(data.code==200){

                    yanse();
                }else{
                	alert(data.msg);
                }
			}

            //点击进度表展示模式
            if(result.type=="click_projectTask"||result.type=="show_planGradation"){

                if(data.code==200){

                    yanse();
                    tempData = [];


                }else{
                }
            }
            //日计划
            if(result.type=="inputPlan_component"){
                if(data.code==200){

                    yanse();
                }
			}
            //进度分析
			if(result.type=="planSearch_component"){
                if(data.code==200){

                    yanse();
                }
			}
			if(result.type=="showRelation_qualityCheck"){
                if(data.code==200){
                    yanse();
                }

			}
			//质量巡查
			if(result.type=="showRelation_qualityPatrol"){
                if(data.code==200){
                    yanse();
                }
			}

			//施工交底
			if(result.type=="showRelation_constructionBottom"){
                if(data.code==200){
                    yanse();
                }
			}

            //点击状态显示隐藏模型
            if(result.type=="show_projectTask"||result.type=="showSome_realProgress"||result.type=="showSome_planNode"||result.type=="showSome_planGradation"||result.type=="showSome_realProgress"){
                if(data.code==200){
                    console.log(result.data);
                    if(result.type=="show_projectTask"||result.type=="showSome_planNode"||result.type=="showSome_planGradation"){
                    	if(result.data.components==0){
                            ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
						}else if(result.data.components==1){
                            ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),true);
                        }else{
                            ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                            ViewerService.defaultViewer.setVisibilityByID(result.data.components,true);
						}

                    }
					if(result.type=="showSome_realProgress"||result.type=="showSome_realProgress"){

                    	var nx=result.data.tags.length;
                        var jobxz00 = sessionStorage.getItem("ztboxys00");
                        var ztboxys00=[];
                        ztboxys00=jobxz00.split(",");

                        var jobxz01= sessionStorage.getItem("ztboxys01");
                        var ztboxys01=[];
                        ztboxys01=jobxz01.split(",");

                        var jobxz02= sessionStorage.getItem("ztboxys02");
                        var ztboxys02=[];
                        ztboxys02=jobxz02.split(",");

                        var jobxz03 = sessionStorage.getItem("ztboxys03");
                        var ztboxys03=[];
                        ztboxys03=jobxz03.split(",");

                        var jobxz04= sessionStorage.getItem("ztboxys04");
                        var ztboxys04=[];
                        ztboxys04=jobxz04.split(",");

                        var jobxz05 = sessionStorage.getItem("ztboxys05");
                        var ztboxys05=[];
                        ztboxys05=jobxz05.split(",");

                        var yansbox=[];
                        for(var nn=0;nn<nx;nn++){
                        	if(result.data.tags[nn]==0){
                                yansbox =yansbox.concat(ztboxys00);
							}
                            if(result.data.tags[nn]==1){
                                yansbox =yansbox.concat(ztboxys01);
                            }
                            if(result.data.tags[nn]==2){
                                yansbox =yansbox.concat(ztboxys02);
                            }
                            if(result.data.tags[nn]==3){
                                yansbox =yansbox.concat(ztboxys03);
                            }
                            if(result.data.tags[nn]==4){
                                yansbox =yansbox.concat(ztboxys04);
                            }
                            if(result.data.tags[nn]==5){
                                yansbox =yansbox.concat(ztboxys05);
                            }
						}

                        ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                        ViewerService.defaultViewer.setVisibilityByID(yansbox,true);




					}


                }
            }
            //模型加载完毕

            function yanse(){
                console.log(result);
                console.log(result.data);
                var qxbox;
                var xzbox
                if(result.type=="planSearch_component"){
                    qxbox=data.rgb[1];
                    xzbox=data.rgb[0];
				}else if(result.type=="click_projectNode"||result.type=="click_projectTask"||result.type=="showRelation_qualityCheck"||result.type=="showRelation_qualityPatrol"||result.type=="showRelation_constructionBottom"){

                    qxbox=rgbjih;
                    xzbox=rgbwjh;
				}else{
                    qxbox=result.data.progress;
                    xzbox=result.data.unprogress;
				}
                qxbox=qxbox.replace("[","");
                qxbox=qxbox.replace("]","");

                xzbox=xzbox.replace("[","");
                xzbox=xzbox.replace("]","");
                sessionStorage.setItem("qxbox",qxbox);
                sessionStorage.setItem("xzbox",xzbox);
                sessionStorage.setItem("moxingys","true");
                // ViewerService.defaultViewer.ssetVisibilityByID(eachChildren(idbox[0]), true);
                //选中id变成亮色
                if(result.type=="click_projectTask"||result.type=="showRelation_constructionBottom"||result.type=="showRelation_qualityPatrol"||result.type=="showRelation_qualityCheck"||result.type=="planSearch_component"||result.type=="showRelation_constructionProgress"||result.type=="show_planNode"||result.type=="show_planGradation"||result.type=="searchPlanByTime_component"||result.type=="showRelation_constructionDaily"){
                    allids=result.data.component_ids;
                    console.log(allids);
				}
				if(result.type=="click_projectNode"){
                    allids=result.data.components;
                    console.log(allids);
				}


                sessionStorage.setItem("localjh",allids);
                setTimeout(function () {
                    ViewerService.defaultViewer.qxselectPartsByID(eachChildren(idbox[0]),false);
                    setTimeout(function () {
                        ViewerService.defaultViewer.xzselectPartsByID(allids,false);
                    }, 20);

                }, 20);
                ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                console.log(allids);
                ViewerService.defaultViewer.setVisibilityByID(allids,true);


                // for(var bb=0;bb<allidboxz;bb++){
                //     for(var cc=0;cc<xuanzhongbox;cc++){
                //         if(eachChildren(idbox[0])[bb]!=allids[cc]){
                //
                //             undefinez.push(eachChildren(idbox[0])[bb]);
                //
                //         }
                //     }
                // }
                // console.log(undefinez);






			}

            console.log(result.type);
            console.log(data);

            if(sessionStorage.getItem("onloadloa")=="true"){
                if(result.type=="showRelation_unitEngineering"&&data.code==200){
                    ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                    ViewerService.defaultViewer.setVisibilityByID(data.component_ids,true);
                }
			}
            if(sessionStorage.getItem("onloadloa")=="true"){
                if(result.type=="showRelation_projectDivision"&&data.code==200){
                    ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                    ViewerService.defaultViewer.setVisibilityByID(data.component_ids,true);
                }
            }
            if(sessionStorage.getItem("onloadloa")=="true"){
                if(result.type=="showRelation_subProject"&&data.code==200){
                    ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                    ViewerService.defaultViewer.setVisibilityByID(data.component_ids,true);
                }
            }



            //模型加载完毕实际进度
			if(result.type=="index_realProgress"||result.type=="reload_realProgress"||result.type=="inputReal_component") {
                sessionStorage.setItem("localwjh",eachChildren(idbox[0]));

                if (getUrlParam('action') == "real" || getUrlParam('action') == "compare"||getUrlParam('action') == "analysis") {
                    var ztboxys00 = [];
                    var ztboxys01 = [];
                    var ztboxys02 = [];
                    var ztboxys03 = [];
                    var ztboxys04 = [];
                    var ztboxys05 = [];

                    var moxleng = data.components.length;

                    console.log(data);


                    rgbwjh=rgbwjh.replace("[","");
                    rgbwjh=rgbwjh.replace("]","");

                    rgbjih=rgbjih.replace("[","");
                    rgbjih=rgbjih.replace("]","");

                    rgb02=rgb02.replace("[","");
                    rgb02=rgb02.replace("]","");

                    rgb03=rgb03.replace("[","");
                    rgb03=rgb03.replace("]","");

                    rgb04=rgb04.replace("[","");
                    rgb04=rgb04.replace("]","");

                    rgb05=rgb05.replace("[","");
                    rgb05=rgb05.replace("]","");

                    sessionStorage.setItem("ysz00", rgbwjh);
                    sessionStorage.setItem("ysz01", rgbjih);
                    sessionStorage.setItem("ysz02", rgb02);
                    sessionStorage.setItem("ysz03", rgb03);
                    sessionStorage.setItem("ysz04", rgb04);
                    sessionStorage.setItem("ysz05", rgb05);


                    for (var i = 0, l = moxleng; i < l; i++) {

                        if (data.components[i]['status'] == "0") {
                            ztboxys00.push(data.components[i]['_id']);
                        }
                        if (data.components[i]['status'] == "1") {
                            ztboxys01.push(data.components[i]['_id']);
                        }
                        if (data.components[i]['status'] == "2") {
                            ztboxys02.push(data.components[i]['_id']);
                        }
                        if (data.components[i]['status'] == "3") {
                            ztboxys03.push(data.components[i]['_id']);
                        }
                        if (data.components[i]['status'] == "4") {
                            ztboxys04.push(data.components[i]['_id']);
                        }
                        if (data.components[i]['status'] == "5") {
                            ztboxys05.push(data.components[i]['_id']);
                        }
                        //ztboxys.push(data.components[i]['_id']);

                        var ztysid = data.components[i]['_id'];
                        // var ztysys=data.components[i]['real_color'];0
                        //     ztysys=ztysys.replace("[","");
                        //      ztysys=ztysys.replace("]","");
                        // sessionStorage.setItem("ztysysbox",ztysys);
                        //ViewerService.defaultViewer.ztysselectPartsByID(ztysid,false);

                    }
                    sessionStorage.setItem("ztboxys00", ztboxys00);
                    sessionStorage.setItem("ztboxys01", ztboxys01);
                    sessionStorage.setItem("ztboxys02", ztboxys02);
                    sessionStorage.setItem("ztboxys03", ztboxys03);
                    sessionStorage.setItem("ztboxys04", ztboxys04);
                    sessionStorage.setItem("ztboxys05", ztboxys05);
                    //ViewerService.defaultViewer.ssetVisibilityByID(eachChildren(idbox[0]), true);
                    // ViewerService.defaultViewer.qxselectPartsByID(eachChildren(idbox[0]),false);
                    ViewerService.defaultViewer.ztysselectPartsByID(ztboxys00, false, 0);
                    ViewerService.defaultViewer.ztysselectPartsByID(ztboxys01, false, 1);
                    ViewerService.defaultViewer.ztysselectPartsByID(ztboxys02, false, 2);
                    ViewerService.defaultViewer.ztysselectPartsByID(ztboxys03, false, 3);
                    ViewerService.defaultViewer.ztysselectPartsByID(ztboxys04, false, 4);
                    ViewerService.defaultViewer.ztysselectPartsByID(ztboxys05, false, 5);
                    // ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
                    ViewerService.defaultViewer.setVisibilityByID(ztboxys00, false);
                    ViewerService.defaultViewer.setVisibilityByID(ztboxys01, false);
                    ViewerService.defaultViewer.setVisibilityByID(ztboxys02, true);
                    ViewerService.defaultViewer.setVisibilityByID(ztboxys03, true);
                    ViewerService.defaultViewer.setVisibilityByID(ztboxys04, true);
                    ViewerService.defaultViewer.setVisibilityByID(ztboxys05, true);


                }
            }




        }
        ws.onclose = function (e) {
            //alert('连接关闭');
        };
        ws.onerror = function (e) {
           // alert(e);
        };

        function sendSocket(type, data){


            data.sn =snbox;
            ws.send(JSON.stringify({
                type: type,
                data:data
            }));
        }

        var intimes=self.setInterval(function () {
            if(sessionStorage.getItem("onloadloa")=="true"){
                clearInterval(intimes);

                $("panel-content md-content").css("overflow-x",null);
                $("panel-content md-content").css("overflow",null);

                setTimeout(function(){
                    sendSocket('index_realProgress', {});
                    //获取安全点
                    if(getUrlParam('action')=="Safety_index"){
                        sendSocket('index_safetyPoint', {});
					}

                    $("#leftPanel #items .md-toolbar-tools .md-flex").text("构件列表");
                    $("#leftPanel #buttons .ng-binding").text("构件");
                    $("#leftPanel #items .md-toolbar-tools .md-flex").css("margin-top","9px");
                    $("#rightPanel #items .md-toolbar-tools .md-flex ").text("问题");
                    $("#rightPanel #buttons .panelButtonGroup ").eq(0).children("label").text("问题");
                    $("#rightPanel #buttons .panelButtonGroup ").eq(1).children("label").text("刨面");
                    $("#rightPanel #buttons .panelButtonGroup ").eq(2).children("label").text("文档");
                    if(getUrlParam('action')=="plan"){
                        //修改左侧树行构件高度
						$(".virtualRepeatInfiniteScroll .vertical-container").css("height","320px");
						$("#items").css("height","380px");
						$("#items").css("overflow","hidden");
					}

                },1000);
            }
        },2000);



        // setTimeout(function(){
         //    ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),false);
         //    setTimeout(function(){
         //        ViewerService.defaultViewer.setVisibilityByID(eachChildren(idbox[0]),true);
		// 	},2000);
        //
		// },20000);


		function setupInfiniteScroll() {
			// Infinite items
			vm.infiniteItemsTree = {
				numLoaded_: 0,
				toLoad_: 0,

				getItemAtIndex: function (index) {
					if (index > this.numLoaded_) {
						this.fetchMoreItems_(index);
						return null;
					}

					if (index < vm.nodesToShow.length) {
						return vm.nodesToShow[index];
					} else {
						return null;
					}
				},

				getLength: function () {
					return this.numLoaded_ + 5;
				},

				fetchMoreItems_: function (index) {
					if (this.toLoad_ < index) {
						this.toLoad_ += 500;
						$timeout(angular.noop, 300).then(angular.bind(this, function () {
							this.numLoaded_ = this.toLoad_;
						}));
					}
				}
			};
		}

		$scope.$watch("vm.filterText", function (newValue) {
			var noFilterItemsFoundHeight = 82;

			if (angular.isDefined(newValue)) {
				if (newValue.toString() === "") {
					vm.showTree = true;
					vm.showFilterList = false;
					vm.showProgress = false;
					vm.nodes = vm.nodesToShow;
					setContentHeight(vm.nodes);
				} else {
					vm.showTree = false;
					vm.showFilterList = false;
					vm.showProgress = true;
					vm.progressInfo = "Filtering tree for objects";

					promise = TreeService.search(newValue);
					promise.then(function (json) {
						vm.showFilterList = true;
						vm.showProgress = false;
						vm.nodes = json.data;
						if (vm.nodes.length > 0) {
							vm.filterItemsFound = true;
							for (i = 0, length = vm.nodes.length; i < length; i += 1) {
								vm.nodes[i].index = i;
								vm.nodes[i].toggleState = "visible";
								vm.nodes[i].class = "unselectedFilterItem";
								vm.nodes[i].level = 0;
							}
							setupInfiniteItemsFilter();
							setContentHeight(vm.nodes);
						}
						else {
							vm.filterItemsFound = false;
							vm.onContentHeightRequest({height: noFilterItemsFoundHeight});
						}
					});
				}
			}
		});

		/**
		 * Selected a node in the tree
		 *
		 * @param node
		 */
		        //点击左侧构件文字调用id实现长链接
				var leftextid=[];
				var paretsid=[];
		vm.selectNode = function (node) {
			//console.log('selectNode');
			// Remove highlight from the current selection and highlight this node if not the same
			if (currentSelectedNode !== null) {
				currentSelectedNode.selected = false;
				if (currentSelectedNode._id === node._id) {
					currentSelectedNode = null;
				}
				else {
					node.selected = true;
					currentSelectedNode = node;
				}
			}
			else {
				node.selected = true;
				currentSelectedNode = node;
			}

			// Remove highlight from the current selection in the viewer and highlight this object if not the same
			if (currentSelectedNode === null) {
				EventService.send(EventService.EVENT.VIEWER.BACKGROUND_SELECTED);
			}
			else {
				var map = [];

				traverseNodeAndPushId(node, map);

				//begin
				var urlname=getUrlParam("action");

				if(urlname=="plan"||urlname=="real"||urlname=="report"||urlname=="construct"||urlname=="check"||urlname=="patrol"||urlname=="build"||urlname=="division"||urlname=="branch"||urlname=="item"){

					if(leftextid.length>0){
						for(var q=0;q<leftextid.length;q++){
							if(node._id==leftextid[q]){
								node.selected=false;
								leftextid.splice(q,1);
								console.log(leftextid);
								break;
							}else {
								if(q==leftextid.length-1){
									node.selected=true;
									leftextid.push(node._id);
									console.log(leftextid);
									break;
								}

							}
						}

					}else{
						node.selected=true;
						leftextid.push(node._id);
					}

				}
				console.log(leftextid);
				//end

				// Select the parent node in the group for cards and viewer
				EventService.send(EventService.EVENT.VIEWER.OBJECT_SELECTED, {
					source: "tree",
					account: node.account,
					project: node.project,
					id: node._id,
					name: node.name
				});

				for(var key in map)
				{
					var vals = key.split("@");
					var account = vals[0];
					var project = vals[1];
				
					// Separately highlight the children
					// but only for multipart meshes
					EventService.send(EventService.EVENT.VIEWER.HIGHLIGHT_OBJECTS, {
						source: "tree",
						account: account,
						project: project,
						ids: map[key]
					});
				}
			}
		};

		vm.filterItemSelected = function (item) {
			if (vm.currentFilterItemSelected === null) {
				vm.nodes[item.index].class = "treeNodeSelected";
				vm.currentFilterItemSelected = item;
			} else if (item.index === vm.currentFilterItemSelected.index) {
				vm.nodes[item.index].class = "";
				vm.currentFilterItemSelected = null;
			} else {
				vm.nodes[vm.currentFilterItemSelected.index].class = "";
				vm.nodes[item.index].class = "treeNodeSelected";
				vm.currentFilterItemSelected = item;
			}

			var selectedNode = vm.nodes[item.index];

			vm.selectNode(selectedNode);
		};

		vm.toggleFilterNode = function (item) {
			vm.setToggleState(item, (item.toggleState === "visible") ? "invisible" : "visible");
			item.path = item._id;
			toggleNode(item);
		};

		function setupInfiniteItemsFilter() {
			vm.infiniteItemsFilter = {
				numLoaded_: 0,
				toLoad_: 0,
				getItemAtIndex: function (index) {
					if (index > this.numLoaded_) {
						this.fetchMoreItems_(index);
						return null;
					}

					if (index < vm.nodes.length) {
						return vm.nodes[index];
					} else {
						return null;
					}
				},
				getLength: function () {
					return this.numLoaded_ + 5;
				},
				fetchMoreItems_: function (index) {
					if (this.toLoad_ < index) {
						this.toLoad_ += 20;
						$timeout(angular.noop, 300).then(angular.bind(this, function () {
							this.numLoaded_ = this.toLoad_;
						}));
					}
				}
			};
		}

		/**
		 * If a node was clicked to hide, add it to a list of similar nodes
		 *
		 * @param {Object} node
		 */
		function updateClickedHidden (node) {
			if (node.toggleState === "invisible") {
				clickedHidden[node._id] = node;
			}
			else {
				delete clickedHidden[node._id];
			}
		}

		/**
		 * If a node was clicked to show, add it to a list of similar nodes
		 *
		 * @param {Object} node
		 */
		function updateClickedShown (node) {
			if (node.toggleState === "visible") {
				clickedShown[node._id] = node;
			}
			else {
				delete clickedShown[node._id];
			}
		}

		/**
		 * Check if a relative in the path was clicked to show
		 *
		 * @param {Object} node
		 */
		function pathRelativeWasClickShown (node) {
			var i, length,
				relativeWasClickShown = false,
				path = node.path.split("__");

			path.pop(); // Remove _id of node from path
			for (i = 0, length = path.length; i < length; i += 1) {
				if (clickedShown.hasOwnProperty(path[i])) {
					relativeWasClickShown = true;
					break;
				}
			}

			return relativeWasClickShown;
		}

		/**
		 * Check if a node was clicked to hide
		 *
		 * @param {Object} node
		 */
		function wasClickedHidden (node) {
			return clickedHidden.hasOwnProperty(node._id);
		}
	}
}());
